package com.texaco.chapasFutbol.entidades;

import org.andengine.engine.camera.Camera;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.AlphaModifier;
import org.andengine.entity.modifier.IEntityModifier.IEntityModifierListener;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.AutoWrap;
import org.andengine.entity.text.Text;
import org.andengine.entity.text.TextOptions;
import org.andengine.opengl.font.IFont;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.util.HorizontalAlign;
import org.andengine.util.modifier.IModifier;

import android.opengl.GLES20;

import com.texaco.chapasFutbol.ChapasFutbolActivity;
import com.texaco.chapasFutbol.R;
import com.texaco.chapasFutbol.resources.Resources;

/**
 * Clase que implementa el HUD Marcador, tiempo restante y turnos restantes.
 * 
 * @author texaco
 * 
 */
public class Hud {
	
	//TODO: TODOS ESTOS VALORES HABRIA QUE LLEVARSELOS O BIEN A LAS CONSTANTES DE STRING O A SU SITIO
	// Shape del hud.
	public static final String SHAPE_HUD = "SHAPE_HUD";
	
	// Shape del logo local.
	public static final String SHAPE_LOGO_LOCAL = "SHAPE_LOGO_LOCAL";
	
	// Shape del logo visitante.
	public static final String SHAPE_LOGO_VISITANTE = "SHAPE_LOGO_VISITANTE";
	
	// Shape del marcador.
	public static final String SHAPE_MARCADOR = "SHAPE_MARCADOR";
	
	// Shape del tiempo.
	public static final String SHAPE_TIEMPO = "SHAPE_TIEMPO"; // Este mismo hueco nos vale para la modalidad de tiempo, goles y turnos.
	
	// Posición X del hud en la hoja de sprites.
	public static final int SHAPE_HUD_X = 3;
	
	// Posición Y del hud en la hoja de sprites.
	public static final int SHAPE_HUD_Y = 3;
	
	// Ancho del hud en la hoja de sprites.
	public static final int HUD_WIDTH = 798 - SHAPE_HUD_X;
	
	// Alto del hud en la hoja de sprites.
	public static final int HUD_HEIGHT = 80 - SHAPE_HUD_Y;

	// Alto de la sombra del HUD, se utiliza para calcular el alto real del hud.
	private static final int HUD_SHADOW_HEIGHT = 7;
	
	// Posición X del logo local en la hoja de sprites.
	public static final int SHAPE_LOGO_LOCAL_X = 7;
	
	// Posición Y del logo local en la hoja de sprites.
	public static final int SHAPE_LOGO_LOCAL_Y = 98;
	
	// Ancho del logo local en la hoja de sprites.
	public static final int LOGO_LOCAL_WIDTH = 62 - SHAPE_LOGO_LOCAL_X;
	
	// Alto del logo local en la hoja de sprites.
	public static final int LOGO_LOCAL_HEIGHT = 145 - SHAPE_LOGO_LOCAL_Y;
	
	// Posición X del logo visitante en la hoja de sprites.
	public static final int SHAPE_LOGO_VISITANTE_X = 87;
	
	// Posición Y del logo visitante en la hoja de sprites.
	public static final int SHAPE_LOGO_VISITANTE_Y = SHAPE_LOGO_LOCAL_Y;
	
	// Ancho del logo visitante en la hoja de sprites.
	public static final int LOGO_VISITANTE_WIDTH = LOGO_LOCAL_WIDTH;
	
	// Alto del logo visitante en la hoja de sprites.
	public static final int LOGO_VISITANTE_HEIGHT = LOGO_LOCAL_HEIGHT;
	
	// Posición X del marcador en la hoja de sprites.
	public static final int SHAPE_MARCADOR_X = 173;
	
	// Posición Y del marcador en la hoja de sprites.
	public static final int SHAPE_MARCADOR_Y = SHAPE_LOGO_LOCAL_Y;
	
	// Ancho del marcador en la hoja de sprites.
	public static final int MARCADOR_WIDTH = 249 - SHAPE_MARCADOR_X;
	
	// Alto del marcador en la hoja de sprites.
	public static final int MARCADOR_HEIGHT = LOGO_LOCAL_HEIGHT;

	// Posición X del tiempo en la hoja de sprites.
	public static final int SHAPE_TIEMPO_X = 280;
	
	// Posición Y del tiempo en la hoja de sprites.
	public static final int SHAPE_TIEMPO_Y = SHAPE_MARCADOR_Y;
	
	// Ancho del tiempo en la hoja de sprites.
	public static final int TIEMPO_WIDTH = 385 - SHAPE_TIEMPO_X;
	
	// Alto del tiempo en la hoja de sprites.
	public static final int TIEMPO_HEIGHT = MARCADOR_HEIGHT;
	
//	public static final int HUD_EN_PANTALLA_X = (int) ((Configurable.CAMERA_WIDTH/2) - (HUD_WIDTH/2));
	public static final int HUD_EN_PANTALLA_Y = 10;

	private static final int MODIFIERS_DURATION = 2;
	private static final float MAX_ALPHA_VALUE = 0.8f;
	private static final float MIN_ALPHA_VALUE = 0.5f;
	private static final float ALFA = MAX_ALPHA_VALUE;

	private int marcadorLocal = 0;
	private int marcadorVisitante = 0;
	public Text mScoreText;
	public Text mRestText;
	public Text mLocalLabel;
	public Text mVisitLabel;
	private int turnos = 0;
	private Game game;
	private int tiempo; // FIXME REQUIERE ESTABLECER EL TIEMPO.
//	public int anchoBarraTurno;
	private Sprite barraHud;
	private Sprite logoLocalHud;
//	public Sprite barraTiempo;
	private Sprite logoVisitanteHud;
	private Sprite marcadorHud;
	private Sprite tiempoHud;
	private Sprite message;

	private boolean oculto = false;
	private boolean mostrado = false;
	private boolean ocultandose = false;
	private boolean mostrandose = false;
	
	private AlphaModifier showModifier = null;
	private AlphaModifier hideModifier = null;

	public Hud(Game game) {
		
		this.game = game;
//		mScoreText = new Text(60 + LOGO_LOCAL_WIDTH, 
//				(HUD_HEIGHT/2)-(LOGO_VISITANTE_HEIGHT/2), 
//				game.getActivity().getFontMap().get(Resources.FONT_HUD), "0 - 0", 150,
//				game.getActivity().getVertexBufferObjectManager());
		mLocalLabel = new Text(74, 
				(HUD_HEIGHT/2)-(LOGO_VISITANTE_HEIGHT/2), 
				game.getActivity().getFontMap().get(Resources.FONT_HUD), 
				"E. Local", "E. Local".length(), // FIXME: REQUIERE SACARLO DE LOS STRINGS
				game.getActivity().getVertexBufferObjectManager());
		mLocalLabel.setBlendFunction(GLES20.GL_SRC_ALPHA,
				GLES20.GL_ONE_MINUS_SRC_ALPHA);
		mLocalLabel.setAlpha(ALFA);
		
		mVisitLabel = new Text(374, 
				(HUD_HEIGHT/2)-(LOGO_VISITANTE_HEIGHT/2), 
				game.getActivity().getFontMap().get(Resources.FONT_HUD), "E. Visitante", "E. Visitante".length(), // FIXME: REQUIERE SACARLO DE LOS STRINGS
				game.getActivity().getVertexBufferObjectManager());
		mVisitLabel.setBlendFunction(GLES20.GL_SRC_ALPHA,
				GLES20.GL_ONE_MINUS_SRC_ALPHA);
		mVisitLabel.setAlpha(ALFA);
		
		mScoreText = new Text(281, 
				(HUD_HEIGHT/2)-(LOGO_VISITANTE_HEIGHT/2), 
				game.getActivity().getFontMap().get(Resources.FONT_HUD), "0 - 0", 7,
				new TextOptions(AutoWrap.WORDS, 358 - 282, HorizontalAlign.CENTER, 0),
				game.getActivity().getVertexBufferObjectManager());
		mScoreText.setBlendFunction(GLES20.GL_SRC_ALPHA,
				GLES20.GL_ONE_MINUS_SRC_ALPHA);
		mScoreText.setAlpha(ALFA);
		
		mRestText = new Text(667, 
				(HUD_HEIGHT/2)-(LOGO_VISITANTE_HEIGHT/2), 
				game.getActivity().getFontMap().get(Resources.FONT_HUD), "3", 7,
				new TextOptions(AutoWrap.WORDS, 782 - 692, HorizontalAlign.CENTER, 0),
				game.getActivity().getVertexBufferObjectManager());
		mRestText.setBlendFunction(GLES20.GL_SRC_ALPHA,
				GLES20.GL_ONE_MINUS_SRC_ALPHA);
		mRestText.setAlpha(ALFA);
		
		barraHud = new Sprite(this.game.getActivity().getResources().getInteger(R.integer.camera_width)/2 - HUD_WIDTH/2,
//				HUD_EN_PANTALLA_X, 
				HUD_EN_PANTALLA_Y, 
				game.getActivity().getShapesMaps().get(SHAPE_HUD), 
				game.getActivity().getVertexBufferObjectManager());
		barraHud.setAlpha(ALFA);

		// A partir de aquí, las posiciones son relativas a la barraHud.
		logoLocalHud = new Sprite(10, ((HUD_HEIGHT - HUD_SHADOW_HEIGHT)/2)-(LOGO_LOCAL_HEIGHT/2), 
				game.getActivity().getShapesMaps().get(SHAPE_LOGO_LOCAL), 
				game.getActivity().getVertexBufferObjectManager());
		logoLocalHud.setAlpha(ALFA);
		
//		logoVisitanteHud = new Sprite(110 + LOGO_LOCAL_WIDTH + MARCADOR_WIDTH, 
//		((HUD_HEIGHT - HUD_SHADOW_HEIGHT)/2)-(LOGO_VISITANTE_HEIGHT/2),
//		game.getActivity().getShapesMaps().get(SHAPE_LOGO_VISITANTE), 
//		game.getActivity().getVertexBufferObjectManager());
		logoVisitanteHud = new Sprite(597,
				((HUD_HEIGHT - HUD_SHADOW_HEIGHT) / 2)
						- (LOGO_VISITANTE_HEIGHT / 2), game.getActivity()
						.getShapesMaps().get(SHAPE_LOGO_VISITANTE), game
						.getActivity().getVertexBufferObjectManager());
		logoVisitanteHud.setAlpha(ALFA);
		
//		marcadorHud = new Sprite(60 + LOGO_LOCAL_WIDTH, 
//				((HUD_HEIGHT - HUD_SHADOW_HEIGHT)/2)-(LOGO_VISITANTE_HEIGHT/2),
//				game.getActivity().getShapesMaps().get(SHAPE_MARCADOR), 
//				game.getActivity().getVertexBufferObjectManager());
		marcadorHud = new Sprite(282, 
				((HUD_HEIGHT - HUD_SHADOW_HEIGHT)/2)-(LOGO_VISITANTE_HEIGHT/2),
				game.getActivity().getShapesMaps().get(SHAPE_MARCADOR), 
				game.getActivity().getVertexBufferObjectManager());
		marcadorHud.setAlpha(ALFA);
		
//		tiempoHud = new Sprite(210 + LOGO_LOCAL_WIDTH + MARCADOR_WIDTH + LOGO_VISITANTE_WIDTH, 
//				((HUD_HEIGHT - HUD_SHADOW_HEIGHT)/2)-(LOGO_VISITANTE_HEIGHT/2),
//				game.getActivity().getShapesMaps().get(SHAPE_TIEMPO), 
//				game.getActivity().getVertexBufferObjectManager());
		tiempoHud = new Sprite(667, 
				((HUD_HEIGHT - HUD_SHADOW_HEIGHT)/2)-(LOGO_VISITANTE_HEIGHT/2),
				game.getActivity().getShapesMaps().get(SHAPE_TIEMPO), 
				game.getActivity().getVertexBufferObjectManager());
		tiempoHud.setAlpha(ALFA);

//		barraTiempo = new Sprite(50, (HUD_HEIGHT) + 10, 
//				game.getActivity().mBarraLocalTextureRegion, 
//				game.getActivity().getVertexBufferObjectManager());
		
		initMessage();

	}
	
//	public void actualizaSpriteBarra(int anchoBarraTurno){
//		barraTiempo.setWidth(anchoBarraTurno);
//	}

	/**
	 * Inicializa el sprite del mensaje.
	 */
	private void initMessage() {
		ChapasFutbolActivity activity = this.game.getActivity();
		Camera cam = activity.getEngine().getCamera();
		
		ITextureRegion messageRegion = activity.getShapesMaps().get(Game.BG_CARTEL_SHAPE);
		float messageX = (cam.getWidthRaw() - messageRegion.getWidth()) * 0.5f;
		float messageY = (cam.getHeightRaw() - messageRegion.getHeight()) * 0.5f;
		message = new Sprite(messageX, messageY, messageRegion, activity.getVertexBufferObjectManager());
		
		TextOptions menTextOpt = new TextOptions(AutoWrap.WORDS, message.getWidth(), HorizontalAlign.CENTER, 0);
		IFont font = activity.getFontMap().get(Resources.FONT_OPTIONS);
		float menTextX = 0;
		float menTextY = (message.getHeight() - font.getLineHeight()) * 0.5f;
		Text messageText = new Text(menTextX, menTextY, font, "", 100, menTextOpt, activity.getVertexBufferObjectManager());
		message.attachChild(messageText);
	}
	
	public Sprite getMessage(int idMessage){
		android.content.res.Resources res = game.getActivity().getResources();
		Text text = (Text) message.getChildByIndex(0);
		text.setText(res.getString(idMessage));
		return message;
	}

	public void incrementaTurno() {
		turnos++;
		actualizaMarcador(marcadorLocal, marcadorVisitante);
	}

	public void incrementaMarcadorLocal() {
		marcadorLocal++;
		actualizaMarcador(marcadorLocal, marcadorVisitante);
	}

	public void incrementaMarcadorVisitante() {
		marcadorVisitante++;
		actualizaMarcador(marcadorLocal, marcadorVisitante);
	}

	public int getMarcadorLocal() {
		return marcadorLocal;
	}
	
	public Sprite getBarraHud() {
		return barraHud;
	}
	
	public Sprite getLogoLocalHud() {
		return logoLocalHud;
	}
	
	public Sprite getLogoVisitanteHud() {
		return logoVisitanteHud;
	}

	public Sprite getMarcadorHud() {
		return marcadorHud;
	}
	
	public Sprite getTiempoHud() {
		return tiempoHud;
	}

//	public Sprite getBarraTiempo() {
//		return barraTiempo;
//	}

	/**
	 * Método que actualiza el valor que indica el marcador.
	 */
	private void actualizaMarcador(int l, int v) {
//		String hud = "L" + l + " - V" + v;
		String hud = l + " - " + v;
		String rest = null;
		if (game.getOpciones().isModoTiempo()) {
			rest = ""+tiempo;
		} else if (game.getOpciones().isModoTurnos()) {
			rest = "T: "
					+ (game.getOpciones().getTurnos() - turnos);
		} else if (game.getOpciones().isModoGoles()) {
			rest = "" + game.getOpciones().getGolesMax();
		}
		mScoreText.setText(hud);
		mRestText.setText(rest);
	}

	/**
	 * Método que pone a 0 todos los marcadores de juego. Así como tiempo o
	 * turnos restantes.
	 */
	public void iniciarMarcadores() {
		marcadorLocal = 0;
		marcadorVisitante = 0;
		turnos = 0;
		tiempo = game.getOpciones().getTiempoMaximo();
//		anchoBarraTurno = game.getOpciones().getAnchoBarraTurnoMaximo();
		actualizaMarcador(marcadorLocal, marcadorVisitante);
	}
	
//	public void inicializarBarraTurno() {
//		anchoBarraTurno = game.getOpciones().getAnchoBarraTurnoMaximo();
//	}

	public void decrementaTiempo() {
		tiempo--;
		actualizaMarcador(marcadorLocal, marcadorVisitante);
	}

//	public void decrementaBarraTiempo() {
//		anchoBarraTurno = anchoBarraTurno-1;
//		actualizaSpriteBarra(anchoBarraTurno);
//	}

	public int getMarcadorVisitante() {
		return marcadorVisitante;
	}

	public Text getmScoreText() {
		return mScoreText;
	}

	public Text getmRestText() {
		return mRestText;
	}

	public Text getmLocalLabel() {
		return mLocalLabel;
	}

	public Text getmVisitLabel() {
		return mVisitLabel;
	}

	public int getTurnos() {
		return turnos;
	}

	public Game getGame() {
		return game;
	}

	public int getTiempo() {
		return tiempo;
	}
	
	/**
	 * Oculta el HUD.
	 * Actualmente aplica un modificador de entidad que le da alpha, pero podria
	 * ser un modificador que oculte el hud de la pantalla.
	 */
	public synchronized void hideHud(){
		if(!ocultandose && !oculto){
			// Borramos los modificadores anteriores.
			barraHud.clearEntityModifiers();
			logoLocalHud.clearEntityModifiers();
			logoVisitanteHud.clearEntityModifiers();
			marcadorHud.clearEntityModifiers();
			tiempoHud.clearEntityModifiers();
			showModifier = null;
			
			hideModifier = new AlphaModifier(MODIFIERS_DURATION, MAX_ALPHA_VALUE, MIN_ALPHA_VALUE, new IEntityModifierListener() {
				public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
					Hud.this.mostrandose = false;
					Hud.this.mostrado = false;
					Hud.this.ocultandose = true;
					Hud.this.oculto = false;
				}
				public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
					Hud.this.mostrandose = false;
					Hud.this.mostrado = false;
					Hud.this.oculto = true;
					Hud.this.ocultandose = false;
				}
			});
			if(hideModifier != null){
				synchronized (hideModifier) {
					// Establecemos los modificadores de ocultar.
					barraHud.registerEntityModifier(hideModifier);
					logoLocalHud.registerEntityModifier(hideModifier);
					logoVisitanteHud.registerEntityModifier(hideModifier);
					marcadorHud.registerEntityModifier(hideModifier);
					tiempoHud.registerEntityModifier(hideModifier);
				}
			}
		}
	}
	
	/**
	 * Muestra el HUD.
	 * Actualmente aplica un modificador de entidad que le da alpha, pero podria
	 * ser un modificador que oculte el hud de la pantalla.
	 */
	public synchronized void showHud(){
		// Borramos los modificadores anteriores.
		barraHud.clearEntityModifiers();
		logoLocalHud.clearEntityModifiers();
		logoVisitanteHud.clearEntityModifiers();
		marcadorHud.clearEntityModifiers();
		tiempoHud.clearEntityModifiers();
		hideModifier = null;

		if(!mostrado && !mostrandose)
			showModifier = new AlphaModifier(MODIFIERS_DURATION, MIN_ALPHA_VALUE, MAX_ALPHA_VALUE, new IEntityModifierListener() {
				public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
					Hud.this.mostrandose = true;
					Hud.this.mostrado = false;
					Hud.this.oculto = false;
					Hud.this.ocultandose = false;
				}
				public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
					Hud.this.mostrandose = false;
					Hud.this.mostrado = true;
					Hud.this.oculto = false;
					Hud.this.ocultandose = false;
				}
			});
		
		if(showModifier != null){
			synchronized (showModifier) {
				// Establecemos los modificadores de mostrar.
				barraHud.registerEntityModifier(showModifier);
				logoLocalHud.registerEntityModifier(showModifier);
				logoVisitanteHud.registerEntityModifier(showModifier);
				marcadorHud.registerEntityModifier(showModifier);
				tiempoHud.registerEntityModifier(showModifier);
			}
		}
	}
	
//	public int getTiempoTurno() {
//		return anchoBarraTurno;
//	}

}
